from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score
from sklearn.datasets import make_blobs

import matplotlib.pyplot as plt
import matplotlib.cm as cm          # matplotlib.cm 色谱
import numpy as np

# 构造模型数据
X, y = make_blobs(n_samples=500
                  ,n_features=2     # 特征数
                  ,centers=5        # 中心
                  ,random_state=3
                  )

# 单个n_clusters看结果
n_clusters = 5
fig, (ax1, ax2) = plt.subplots(1, 2)        # 子图：生成1行2列，1*2个图
fig.set_size_inches(10, 5)

# 设置ax1
ax1.set_xlim([-0.1, 1])     # x轴：-0.1到1
ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])       # y轴：0到样本数+（簇数+1）*10

clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
cluster_labels = clusterer.labels_  # 每个样本聚类的簇的编号
silhouette_avg = silhouette_score(X, cluster_labels)    # 轮廓系数均值
print("For n_clusters =", n_clusters,
      "The average silhouette_score is :", silhouette_avg)          # 打印簇数是n时，平均轮廓系数是xxx
sample_silhouette_values = silhouette_samples(X, cluster_labels)    # 每个样本的轮廓系数值

y_lower = 10
for i in range(n_clusters):
    ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]   # 每个簇样本的轮廓系数
    ith_cluster_silhouette_values.sort()                                # 排序
    size_cluster_i = ith_cluster_silhouette_values.shape[0]             # 该簇的样本数
    y_upper = y_lower + size_cluster_i                                  # 根据样本数设置y轴最大值
    color = cm.nipy_spectral(float(i)/n_clusters)                       # cm.nipy_spectral（）函数，赋给它不同的浮点数数值能够生成不同的颜色。
    # fill_betweenx 覆盖图
    ax1.fill_betweenx(np.arange(y_lower, y_upper)                       # 设置y轴
                     ,ith_cluster_silhouette_values                     # x轴是该簇所有样本的轮廓系数
                     ,facecolor=color
                     ,alpha=0.7
                     )
    ax1.text(-0.05
             , y_lower + 0.5 * size_cluster_i
             , str(i))
    y_lower = y_upper + 10                                              # 不同簇的y轴错开，间隔10
# 图标名称和坐标轴说明
ax1.set_title("The silhouette plot for the various clusters.")
ax1.set_xlabel("The silhouette coefficient values")
ax1.set_ylabel("Cluster label")

ax1.axvline(x=silhouette_avg, color="red", linestyle="--")              # 添加垂直直线，axhline是水平直线
ax1.set_yticks([])                                                      # 设置y轴刻度
ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])                        # 设置x轴刻度

# 设置ax2
colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)    # 设置颜色
ax2.scatter(X[:, 0], X[:, 1]                                            # X的散点图
           ,marker='o' #点的形状
           ,s=8 #点的大小
           ,c=colors
           )
centers = clusterer.cluster_centers_                                    # 质心
ax2.scatter(centers[:, 0], centers[:, 1], marker='x',
            c="red", alpha=1, s=200)

# 图标名称和坐标轴说明
ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")
# 添加总标题
plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
              "with n_clusters = %d" % n_clusters),
             fontsize=14, fontweight='bold')
plt.show()


# 使用循环观察各种n_clusters的结果
# for n_clusters in [2,3,4,5,6,7]:
#     n_clusters = n_clusters
#     fig, (ax1, ax2) = plt.subplots(1, 2)
#     fig.set_size_inches(18, 7)
#     ax1.set_xlim([-0.1, 1])
#     ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])
#     clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)
#     cluster_labels = clusterer.labels_
#     silhouette_avg = silhouette_score(X, cluster_labels)
#     print("For n_clusters =", n_clusters,
#           "The average silhouette_score is :", silhouette_avg)
#     sample_silhouette_values = silhouette_samples(X, cluster_labels)
#     y_lower = 10
#     for i in range(n_clusters):
#         ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
#         ith_cluster_silhouette_values.sort()
#         size_cluster_i = ith_cluster_silhouette_values.shape[0]
#         y_upper = y_lower + size_cluster_i
#         color = cm.nipy_spectral(float(i)/n_clusters)
#         ax1.fill_betweenx(np.arange(y_lower, y_upper)
#                          ,ith_cluster_silhouette_values
#                          ,facecolor=color
#                          ,alpha=0.7
#                          )
#         ax1.text(-0.05
#                  , y_lower + 0.5 * size_cluster_i
#                  , str(i))
#         y_lower = y_upper + 10
#     ax1.set_title("The silhouette plot for the various clusters.")
#     ax1.set_xlabel("The silhouette coefficient values")
#     ax1.set_ylabel("Cluster label")
#     ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
#     ax1.set_yticks([])
#     ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
#     colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
#     ax2.scatter(X[:, 0], X[:, 1]
#                ,marker='o' #点的形状
#                ,s=8 #点的大小
#                ,c=colors
#                )
#     centers = clusterer.cluster_centers_
#     ax2.scatter(centers[:, 0], centers[:, 1], marker='x',
#                 c="red", alpha=1, s=200)
#     ax2.set_title("The visualization of the clustered data.")
#     ax2.set_xlabel("Feature space for the 1st feature")
#     ax2.set_ylabel("Feature space for the 2nd feature")
#     plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
#                   "with n_clusters = %d" % n_clusters),
#                  fontsize=14, fontweight='bold')
#     plt.show()
